/*
 * FieldAssociation.scala
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package org.squela

import scala.collection.JavaConversions._

object FieldAssociation {

  def associate(obj: AnyRef, fieldsList: Field[_]*): Seq[->[_]] = associate(null, obj, fieldsList:_*)
  def associate(bindings: Bindings, obj: AnyRef, fieldsList: Field[_]*): Seq[->[_]] = {
    val methods = Utils.getMethodsForClass(obj.getClass)
    @inline def associate[T](f: Field[T]) = {
      if(bindings != null && bindings.contains(f)) {
        f->bindings(f).getter(obj)
      } else {
        val scalaGetter = f.name
        val javaGetter = "get" + f.name
        val opt = methods find (m => (m.getName equalsIgnoreCase scalaGetter) || (m.getName equalsIgnoreCase javaGetter))
        require(!opt.isEmpty, "Not found getter for " + f.name + " in " + obj.getClass)
        f->opt.get.invoke(obj).asInstanceOf[T]
      }
    }
    fieldsList map (associate(_))
  }
}

abstract class FieldAssociation extends LogicalLink {
  type FieldType
  val field: Field[_]
  var value: FieldType
}

case class >[T](override val field: Field[T], override var value: T) extends FieldAssociation{type FieldType = T}
case class >=[T](override val field: Field[T], override var value: T) extends FieldAssociation{type FieldType = T}
case class <[T](override val field: Field[T], override var value: T) extends FieldAssociation{type FieldType = T}
case class <=[T](override val field: Field[T], override var value: T) extends FieldAssociation{type FieldType = T}
case class ->[T](override val field: Field[T], override var value: T) extends FieldAssociation{type FieldType = T}
case class <>[T](override val field: Field[T], override var value: T) extends FieldAssociation{type FieldType = T}
case class Like(override val field: Field[String], override var value: String) extends FieldAssociation{type FieldType = String}
case class In(override val field: Field[_], override var value: Query) extends FieldAssociation{type FieldType = Query}
